{
  "name": "Case 61 - New Product Launch Competitor",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 9
            }
          ]
        }
      },
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        -1040,
        -96
      ],
      "id": "35abb71e-68dd-47e1-95cc-61f0b9af486c",
      "name": "Daily Schedule - 9 AM"
    },
    {
      "parameters": {
        "actorId": {
          "__rl": true,
          "value": "nH2AHrwxeTRJoN5hX",
          "mode": "list",
          "cachedResultName": "Instagram Post Scraper (apify/instagram-post-scraper)",
          "cachedResultUrl": "https://console.apify.com/actors/nH2AHrwxeTRJoN5hX/input"
        },
        "customBody": "={\n  \"onlyPostsNewerThan\": \"{{ new Date(Date.now() - 60*24*60*60*1000).toISOString().split('T')[0] }}\",\n  \"resultsLimit\": 50,\n  \"skipPinnedPosts\": false,\n  \"username\": [\n    \"@apple\",\n    \"@samsung\",\n    \"@tesla\"\n  ]\n}"
      },
      "type": "@apify/n8n-nodes-apify.apify",
      "typeVersion": 1,
      "position": [
        -832,
        -96
      ],
      "id": "629b7bf6-c641-43bc-89ce-247d18f7ab8b",
      "name": "Scrape Competitor Instagram",
      "credentials": {
        "apifyApi": {
          "id": "w5S6YBbbyUddEfQA",
          "name": "Apify account"
        }
      }
    },
    {
      "parameters": {
        "resource": "Datasets",
        "datasetId": "={{ $json.defaultDatasetId }}",
        "limit": 150
      },
      "type": "@apify/n8n-nodes-apify.apify",
      "typeVersion": 1,
      "position": [
        -640,
        -96
      ],
      "id": "6619dfa0-9306-4b24-b5dc-c8f3d5fc6062",
      "name": "Get Dataset Items",
      "credentials": {
        "apifyApi": {
          "id": "w5S6YBbbyUddEfQA",
          "name": "Apify account"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 1
          },
          "conditions": [
            {
              "id": "condition-001",
              "leftValue": "={{ $json.caption }}",
              "rightValue": "launch",
              "operator": {
                "type": "string",
                "operation": "contains",
                "singleValue": true
              }
            },
            {
              "id": "condition-002",
              "leftValue": "={{ $json.caption }}",
              "rightValue": "new product",
              "operator": {
                "type": "string",
                "operation": "contains"
              }
            },
            {
              "id": "condition-003",
              "leftValue": "={{ $json.caption }}",
              "rightValue": "now available",
              "operator": {
                "type": "string",
                "operation": "contains"
              }
            },
            {
              "id": "condition-004",
              "leftValue": "={{ $json.caption }}",
              "rightValue": "introducing",
              "operator": {
                "type": "string",
                "operation": "contains"
              }
            },
            {
              "id": "condition-005",
              "leftValue": "={{ $json.caption }}",
              "rightValue": "unveiling",
              "operator": {
                "type": "string",
                "operation": "contains"
              }
            },
            {
              "id": "condition-006",
              "leftValue": "={{ $json.caption }}",
              "rightValue": "just dropped",
              "operator": {
                "type": "string",
                "operation": "contains"
              }
            },
            {
              "id": "condition-007",
              "leftValue": "={{ $json.caption }}",
              "rightValue": "pre-order",
              "operator": {
                "type": "string",
                "operation": "contains"
              }
            }
          ],
          "combinator": "or"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2,
      "position": [
        -432,
        -96
      ],
      "id": "40af0430-f217-4e66-9598-0ffd9cb93fc8",
      "name": "Filter Launch Keywords"
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "gpt-4o-mini",
          "mode": "list",
          "cachedResultName": "GPT-4o-mini"
        },
        "responses": {
          "values": [
            {
              "role": "system",
              "content": "=You are a Product Launch Information Extraction Agent.\n\nExtract structured product launch data from Instagram posts.\n\nReturn ONLY valid JSON in this exact format:\n{\n  \"product_name\": \"exact product name mentioned\",\n  \"launch_date\": \"YYYY-MM-DD format, or 'TBA' if not specified\",\n  \"category\": \"choose one: smartphone|tablet|laptop|wearable|accessory|software|service|vehicle|apparel|other\",\n  \"price\": \"extract price with currency symbol, or null if not mentioned\",\n  \"key_features\": [\"feature 1\", \"feature 2\", \"feature 3\"]\n}\n\nRules:\n1. Use null if information is not found\n2. Extract top 3 features maximum\n3. Be precise with dates - look for specific dates in caption\n4. Normalize category to the provided options\n5. Return ONLY the JSON object, no explanations or markdown"
            },
            {
              "content": "=Analyze this Instagram post and extract product launch information:\n\nUsername: {{ $json.ownerUsername }}\nPost Date: {{ $json.timestamp }}\nCaption: {{ $json.caption }}\n\nReturn only JSON."
            }
          ]
        },
        "builtInTools": {},
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 2.1,
      "position": [
        -224,
        -96
      ],
      "id": "163d74a3-75f3-42dc-8310-5dedddcda05a",
      "name": "AI Extract Launch Data",
      "credentials": {
        "openAiApi": {
          "id": "ICwxUBbatsF2sDvy",
          "name": "OpenAi account"
        }
      }
    },
    {
      "parameters": {
        "sendTo": "product-team@yourcompany.com",
        "subject": "=🚀 New Product Launch: {{ $json.competitor }} - {{ $json.product_name }}",
        "message": "=<html>\n<head>\n  <style>\n    body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }\n    .container { max-width: 900px; margin: 0 auto; padding: 20px; }\n    .header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px; border-radius: 10px 10px 0 0; }\n    table { width: 100%; border-collapse: collapse; margin: 20px 0; background: white; }\n    th { background: #667eea; color: white; padding: 12px; text-align: left; }\n    td { padding: 10px; border-bottom: 1px solid #ddd; }\n    tr:hover { background: #f5f5f5; }\n    .footer { text-align: center; color: #666; font-size: 12px; margin-top: 20px; padding-top: 10px; border-top: 1px solid #ddd; }\n  </style>\n</head>\n<body>\n  <div class=\"container\">\n    <div class=\"header\">\n      <h2 style=\"margin: 0;\">🚀 Daily Competitor Product Launch Report</h2>\n      <p style=\"margin: 5px 0 0 0;\">{{ $json.total_launches }} new product launches detected</p>\n    </div>\n    \n    <table>\n      <thead>\n        <tr>\n          <th>Competitor</th>\n          <th>Product</th>\n          <th>Category</th>\n          <th>Launch Date</th>\n          <th>Price</th>\n          <th>Engagement</th>\n          <th>Link</th>\n        </tr>\n      </thead>\n      <tbody>\n        {{ $json.table_rows }}\n      </tbody>\n    </table>\n    \n    <div class=\"footer\">\n      <p>Report Generated: {{ new Date().toLocaleString() }}</p>\n      <p>Automated Competitive Intelligence System | Case 61</p>\n    </div>\n  </div>\n</body>\n</html>",
        "options": {}
      },
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        864,
        -96
      ],
      "id": "3ad8686c-d141-470e-a296-a213ee9bd010",
      "name": "Send Email Alert",
      "webhookId": "ae5e72e1-db7a-4832-89b0-4fc205b6fbcf",
      "credentials": {
        "gmailOAuth2": {
          "id": "cyqCGWcggZNMcSOv",
          "name": "Gmail account"
        }
      }
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "11Xd9BZUw6ShBvO1vt6jBzwH2uIIRG9jKl3ZQqs5mmCQ",
          "mode": "list",
          "cachedResultName": "Case 61 - Competitor Product Launch Log",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/11Xd9BZUw6ShBvO1vt6jBzwH2uIIRG9jKl3ZQqs5mmCQ/edit?usp=drivesdk"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "list",
          "cachedResultName": "Sheet1",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/11Xd9BZUw6ShBvO1vt6jBzwH2uIIRG9jKl3ZQqs5mmCQ/edit#gid=0"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "Detected_Date": "={{ $json.detected_timestamp }}",
            "Competitor": "={{ $json.competitor }}",
            "Product_Name": "={{ $json.product_name }}",
            "Category": "={{ $json.category }}",
            "Launch_Date": "={{ $json.launch_date }}",
            "Price": "={{ $json.price }}",
            "Key_Features": "={{ $json.key_features }}",
            "Post_URL": "={{ $json.post_url }}",
            "Post_Caption": "={{ $json.post_caption }}",
            "Likes": "={{ $json.likes_count }}",
            "Comments": "={{ $json.comments_count }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "Detected_Date",
              "displayName": "Detected_Date",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Competitor",
              "displayName": "Competitor",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Product_Name",
              "displayName": "Product_Name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Category",
              "displayName": "Category",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Launch_Date",
              "displayName": "Launch_Date",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Price",
              "displayName": "Price",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Key_Features",
              "displayName": "Key_Features",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Post_URL",
              "displayName": "Post_URL",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Likes",
              "displayName": "Likes",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Comments",
              "displayName": "Comments",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "Post_Caption",
              "displayName": "Post_Caption",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        528,
        -96
      ],
      "id": "be4b4f91-af3a-4704-bb60-5b94a2f18577",
      "name": "Log to Google Sheet",
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "LOs2dbk9lby0NfDM",
          "name": "Google Sheets account"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Aggregate all items from Google Sheets into email-ready object\nconst allItems = $input.all();\n\n// Build HTML table rows for email\nconst tableRows = allItems.map(item => {\n  const data = item.json;\n  \n  // Handle Key_Features - it's now a string from Google Sheets\n  const features = data.Key_Features || '';\n  \n  return `\n    <tr>\n      <td>${data.Competitor || 'N/A'}</td>\n      <td><strong>${data.Product_Name || 'N/A'}</strong></td>\n      <td>${data.Category || 'N/A'}</td>\n      <td>${data.Launch_Date || 'N/A'}</td>\n      <td>${data.Price || 'N/A'}</td>\n      <td>${(parseInt(data.Likes) || 0).toLocaleString()}</td>\n      <td><a href=\"${data.Post_URL || '#'}\">View Post</a></td>\n    </tr>\n  `;\n}).join('');\n\n// Return single item with aggregated data\nreturn {\n  json: {\n    total_launches: allItems.length,\n    table_rows: tableRows,\n    launches: allItems.map(item => item.json)\n  }\n};"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        688,
        -96
      ],
      "id": "c8c3dc9d-3f3d-4d30-b9cf-c51fc569449f",
      "name": "Aggregate all items"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "timestamp",
              "name": "detected_timestamp",
              "value": "={{ new Date().toISOString() }}",
              "type": "string"
            },
            {
              "id": "competitor",
              "name": "competitor",
              "value": "={{ $('Filter Launch Keywords').item.json.ownerUsername }}",
              "type": "string"
            },
            {
              "id": "product",
              "name": "product_name",
              "value": "={{ $json.product_name }}",
              "type": "string"
            },
            {
              "id": "launch",
              "name": "launch_date",
              "value": "={{ $json.launch_date }}",
              "type": "string"
            },
            {
              "id": "category",
              "name": "category",
              "value": "={{ $json.category }}",
              "type": "string"
            },
            {
              "id": "price",
              "name": "price",
              "value": "={{ $json.price }}",
              "type": "string"
            },
            {
              "id": "features",
              "name": "key_features",
              "value": "={{ $json.key_features }}",
              "type": "array"
            },
            {
              "id": "url",
              "name": "post_url",
              "value": "={{ $('Filter Launch Keywords').item.json.url }}",
              "type": "string"
            },
            {
              "id": "caption",
              "name": "post_caption",
              "value": "={{ $('Filter Launch Keywords').item.json.caption }}",
              "type": "string"
            },
            {
              "id": "postdate",
              "name": "post_date",
              "value": "={{ $('Filter Launch Keywords').item.json.timestamp }}",
              "type": "string"
            },
            {
              "id": "likes",
              "name": "likes_count",
              "value": "={{ $('Filter Launch Keywords').item.json.likesCount }}",
              "type": "number"
            },
            {
              "id": "comments",
              "name": "comments_count",
              "value": "={{ $('Filter Launch Keywords').item.json.commentsCount }}",
              "type": "number"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        320,
        -96
      ],
      "id": "9babe85d-ee2d-4699-9398-3df4f9305cc0",
      "name": "Edit Fields"
    },
    {
      "parameters": {
        "jsCode": "// UNIVERSAL AI RESPONSE PARSER - BLACK BOX (Students don't need to modify)\nconst items = [];\nconst input = $input.all();\n\nfunction extractJSON(text) {\n  const jsonMatch = text.match(/\\{[\\s\\S]*\\}/);\n  if (!jsonMatch) return null;\n  return jsonMatch[0];\n}\n\ninput.forEach((item, index) => {\n  try {\n    let aiText = item.json.output[0].content[0].text || '';\n    \n    // Clean markdown code blocks\n    aiText = aiText\n      .replace(/```json/gi, '')\n      .replace(/```/g, '')\n      .trim();\n    \n    // Extract JSON object\n    const jsonStr = extractJSON(aiText);\n    \n    if (!jsonStr) {\n      throw new Error('No JSON found in AI response');\n    }\n    \n    // Parse to clean JSON\n    const parsed = JSON.parse(jsonStr);\n    \n    items.push({ json: parsed });\n    \n  } catch (error) {\n    console.error(`Parse error for item ${index}:`, error.message);\n    \n    // Return empty object on error\n    items.push({\n      json: {\n        product_name: null,\n        launch_date: null,\n        category: null,\n        price: null,\n        key_features: []\n      }\n    });\n  }\n});\n\nreturn items;"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        128,
        -96
      ],
      "id": "784b575b-69a3-4929-8b63-2aab9f91b1da",
      "name": "Parse AI Response"
    }
  ],
  "pinData": {},
  "connections": {
    "Daily Schedule - 9 AM": {
      "main": [
        [
          {
            "node": "Scrape Competitor Instagram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scrape Competitor Instagram": {
      "main": [
        [
          {
            "node": "Get Dataset Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Dataset Items": {
      "main": [
        [
          {
            "node": "Filter Launch Keywords",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Launch Keywords": {
      "main": [
        [
          {
            "node": "AI Extract Launch Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Extract Launch Data": {
      "main": [
        [
          {
            "node": "Parse AI Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log to Google Sheet": {
      "main": [
        [
          {
            "node": "Aggregate all items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate all items": {
      "main": [
        [
          {
            "node": "Send Email Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields": {
      "main": [
        [
          {
            "node": "Log to Google Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Response": {
      "main": [
        [
          {
            "node": "Edit Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "ffc3868a-bdd1-444f-848c-3cb23d7a1ed2",
  "meta": {
    "templateCredsSetupCompleted": true,
    "instanceId": "3a43da28588548e21903e71cf1dc3ddd65c24bf0c62e7e4b77542ffe87ad79c6"
  },
  "id": "3iF58MZIvJnfDn0j",
  "tags": []
}